using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameStateManagement.GameHelper;

namespace _0812367_0912581
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class GameLevel : Microsoft.Xna.Framework.DrawableGameComponent
    {
        public GameLevel(Game game, SpriteBatch theSpriteBatch)
            : base(game)
        {
            // TODO: Construct any child components here
            this.spriteBatch = theSpriteBatch;
        }

        protected SpriteBatch spriteBatch;

        //State Level
        public enum StateLevel
        {
            Begin,
            Medium,
            Difficult,
            Finally,
            End,
        };

        public int stateLevel;


        private const int NUMBLE_PLAYER_SPRITE = 9;
        private const int NUMBLE_MONTER_SPRITE = 8;
        private const int PLAYER_BULLET_TEXTURE = 1;
        private const int MONTER_BULLET_TEXTURE = 1;
        private const int LINE = 5;

        //Player 
        protected Texture2D[] playerTexture;
        protected int playerMoney;
        protected int nPlayerSprite;// So loai Player Sprite cua Level
        protected PlayerSprite[] playerSprite;// sprite mau
        protected List<PlayerSprite> listPlayerSpriteDraw;//chua cac con sprite dang dc ve
        PlayerSprite termSprite = null, termSprite1 = null;
        public static int score = 0;

        //public int Score
        //{
        //    get { return score; }
        //    set { score = value; }
        //}
        protected int PLAYERMONEY_BEGIN = 200;


        //Bullets
        protected Texture2D[] playerBulletTexture;
        protected Texture2D[] monterBulletTexture;


        //Monter
        protected Texture2D[] monterTexture;
        protected int nMonterSprite;// so loai Monter cua level
        protected int TOTALMONTER;// so luong monter trong moi Level
        protected int remainMonterSprite;
        protected int NUMBER_MONTER_BEGIN;
        protected int numberMonterSpriteAtTime;// so luong monter tai mot o moi StateLevel
        protected int INCREASE = 5;
        protected int curNumberMonter;
        protected EnemySprite[] monterSprite;//sprite mau
        protected List<EnemySprite> listMonterSprite;//chua cac con sprite dang dc ve
        protected int timeCreateMonter = 1000;
        protected int timeLastCreateMonter = 0;
        protected int COSTONESPRITE = 30;

        // draw menu sprite choose
        protected float dx;
        protected float dy;

        //MouseState
        MouseState curMouseState;
        MouseState preMouseState;

        //Sound 
        SoundEffect mySound;
        SoundEffectInstance mySoundInstance;

        //Draw Money, Score
        SpriteFont spriteFont;

        //
       // protected int MONTERACROSS = 3;
        public static int monterAcross = 3;

        //Sound
        SoundEffect playerBulletSound;
        SoundEffect monterBulletSound;
        SoundEffect monterCollisionSound;
        Song baseSound;
        SoundEffectInstance baseSoundInstance;

        Texture2D liveTexture;



        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }


        public virtual void LoadContent(ContentManager theContent)
        {
            playerTexture = new Texture2D[NUMBLE_PLAYER_SPRITE];
            monterTexture = new Texture2D[NUMBLE_MONTER_SPRITE];
            playerBulletTexture = new Texture2D[PLAYER_BULLET_TEXTURE];
            monterBulletTexture = new Texture2D[MONTER_BULLET_TEXTURE];

            for (int i = 0; i < PLAYER_BULLET_TEXTURE; i++)
            {
                playerBulletTexture[i] = theContent.Load<Texture2D>("Resources\\PlayerBullet" + (i + 1).ToString());
            }

            for (int i = 0; i < MONTER_BULLET_TEXTURE; i++)
            {
                monterBulletTexture[i] = theContent.Load<Texture2D>("Resources\\MonterBullet" + (i + 1).ToString());
            }

            for (int i = 0; i < NUMBLE_PLAYER_SPRITE; i++)
            {
                playerTexture[i] = theContent.Load<Texture2D>("Resources\\player" + (i + 1).ToString("00"));
            }

            for (int i = 0; i < NUMBLE_MONTER_SPRITE; i++)
            {
                monterTexture[i] = theContent.Load<Texture2D>("Resources\\monter" + (i + 1).ToString("00"));
            }

            liveTexture = theContent.Load<Texture2D>("Resources\\Live");

            this.spriteFont = theContent.Load<SpriteFont>("menufont");

            //Sound
            playerBulletSound = theContent.Load<SoundEffect>("Sound\\PlayerBulletCollision");
            monterBulletSound = theContent.Load<SoundEffect>("Sound\\MonterBulletCollision");
            monterCollisionSound = theContent.Load<SoundEffect>("Sound\\MonterCollision");
            baseSound = theContent.Load<Song>("Sound\\Choose Your Seeds - Laura Shigihara");

            if (GameSettings.Instance.AudioEnable)
                MediaPlayer.Play(baseSound);
            
            

            this.stateLevel = (int)StateLevel.Begin;
            //this.playerMoney = this.PLAYERMONEY_BEGIN;

        }




        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public virtual void Update(GameTime gameTime)
        {
            // TODO: Add your update code here            
            //if (baseSoundInstance.State == SoundState.Stopped)
            //{
            //    baseSoundInstance.IsLooped = true;
            //    baseSoundInstance.Play();
                
            //}
            //else
            //    if (baseSoundInstance.State == SoundState.Paused)
            //    {
            //        baseSoundInstance.Resume();
            //    }

            UpdateMonter(gameTime);
            UpdatePlayer(gameTime);
            UpdateCollision(gameTime);

            // player choose sprite
            termSprite = null;//**************
            curMouseState = Mouse.GetState();

            if (curMouseState.LeftButton == ButtonState.Pressed && preMouseState.LeftButton == ButtonState.Released)
            {
                float x = curMouseState.X;
                float y = curMouseState.Y;
                int n = playerSprite.Length;
                for (int i = 0; i < n; i++)
                {
                    float left = playerSprite[i].Position.X;
                    float right = playerSprite[i].Position.X + playerSprite[i].FrameSize.X * playerSprite[i].Scale;
                    float top = dy;
                    float bottom = dy + playerSprite[i].FrameSize.Y * playerSprite[i].Scale;

                    if (CheckRangeClick(curMouseState, left, right, top, bottom))
                    {
                        if (this.playerMoney >= COSTONESPRITE)
                        {
                            switch (i)
                            {
                                case 0:
                                    termSprite = new PlayerSprite(playerSprite[0]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.0f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 1:
                                    termSprite = new PlayerSprite(playerSprite[1]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.0f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 2:
                                    termSprite = new PlayerSprite(playerSprite[2]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.3f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 3:
                                    termSprite = new PlayerSprite(playerSprite[3]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 0.8f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 4:
                                    termSprite = new PlayerSprite(playerSprite[4]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 0.9f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 5:
                                    termSprite = new PlayerSprite(playerSprite[5]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.1f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 6:
                                    termSprite = new PlayerSprite(playerSprite[6]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.0f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 7:
                                    termSprite = new PlayerSprite(playerSprite[7]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 1.4f;
                                    termSprite1 = termSprite;
                                    //listPlants.Add(termSprite);
                                    break;
                                case 8:
                                    termSprite = new PlayerSprite(playerSprite[8]);
                                    termSprite.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                    termSprite.Scale = 0.7f;
                                    termSprite1 = termSprite;
                                    break;
                            }
                        }
                        break;//khoi vong for

                    }

                    else // click chuot ngoai vung chon
                        if (termSprite1 != null)//co click vao vung chon truoc do
                        {
                            if (curMouseState.Y > (dy + playerSprite[0].FrameSize.Y - playerSprite[0].CollisionOffset * 2))// duoi vung menu choose moi dc ve
                            {
                                termSprite1.Position = new Vector2(curMouseState.X, curMouseState.Y);
                                listPlayerSpriteDraw.Add(termSprite1);
                                termSprite1 = null;
                                this.playerMoney -= COSTONESPRITE;
                            }
                        }

                }

            }
            preMouseState = curMouseState;

            base.Update(gameTime);
        }

        public virtual void Draw(GameTime gameTime)
        {
            int n = playerSprite.Length;
            curMouseState = Mouse.GetState();

            if (this.playerMoney < COSTONESPRITE)
            {
                for (int i = 0; i < n; i++)// Draw menu choose sprites
                {
                    playerSprite[i].Draw(gameTime, this.spriteBatch, Color.YellowGreen);
                }
            }
            else
            {
                for (int i = 0; i < n; i++)// Draw menu choose sprites
                {
                    playerSprite[i].Draw(gameTime, this.spriteBatch, Color.WhiteSmoke);
                }
            }

            if (termSprite1 != null)// di chuyen theo toa do chuot
            {
                termSprite1.Position = new Vector2(curMouseState.X, curMouseState.Y);//chu y
                //listPlants.Add(termSprite);
                termSprite1.Draw(gameTime, this.spriteBatch);
            }

            preMouseState = curMouseState;

            foreach (PlayerSprite sprite in listPlayerSpriteDraw)//Cac con sprite cua player
            {
                if (sprite.IsLiving)
                {
                    sprite.Draw(gameTime, this.spriteBatch);
                }
            }
            //for (int i = 0; i < nMonterSprite; i++)
            //{
            //    monterSprite[i].Draw(gameTime, this.spriteBatch);
            //}

            foreach (EnemySprite monter in listMonterSprite)
            {
                if (monter.IsLiving)
                {
                    monter.Draw(gameTime, this.spriteBatch);
                }
            }

            spriteBatch.DrawString(this.spriteFont, "Score: " + GameLevel.score, new Vector2(200, 70), Color.White);
            spriteBatch.DrawString(this.spriteFont, "Money: " + this.playerMoney, new Vector2(30, 70), Color.White);

            //Ve so mang con lai
            int d0 = 300;
            for (int i = 0; i < monterAcross; i++)
            {
                //spriteBatch.Draw(liveTexture, new Rectangle(d0, 5, (int)(liveTexture.Width * 0.5f), (int)(liveTexture.Height * 0.5f)), Color.White);
                //d0 = (int)(d0 + liveTexture.Width * 0.5f);
            }
            //spriteBatch
            base.Draw(gameTime);
        }


        public virtual void UpdateMonter(GameTime gameTime)
        {
            //Loai nhung con monter chet
            for (int i = 0; i < listMonterSprite.Count; i++)
            {
                if (listMonterSprite[i].IsLiving == false)
                {
                    listMonterSprite.RemoveAt(i);
                    //--totalMonterSprite;
                    remainMonterSprite--;
                    curNumberMonter--;
                    this.playerMoney += 20;
                    GameLevel.score += 50;
                }
            }

            //Update nhung Monter tren man hinh
            foreach (EnemySprite monter in listMonterSprite)
            {
                monter.Update(gameTime);
                if (monter.Position.X <= 0)
                {
                    GameLevel.monterAcross--;
                }
               
            }

            // Update SateLevel
            if (remainMonterSprite > TOTALMONTER * 3 / 4)
            {
                stateLevel = (int)StateLevel.Begin;
            }
            else
                if (remainMonterSprite > TOTALMONTER / 2)
                {
                    stateLevel = (int)StateLevel.Medium;
                    this.numberMonterSpriteAtTime += this.INCREASE;
                }
                else
                    if(remainMonterSprite > TOTALMONTER/4)
                    {
                        stateLevel = (int)StateLevel.Difficult;
                        this.numberMonterSpriteAtTime += this.INCREASE;
                    }
                    else
                        if(remainMonterSprite > 0)
                        {
                            stateLevel = (int)StateLevel.Finally;
                            this.numberMonterSpriteAtTime += this.INCREASE;
                        }
                        else
                        {
                            stateLevel = (int)StateLevel.End;
                        }
                    

            //Create Monter
            if (remainMonterSprite > 0)
            {
                CreateMonter(gameTime);
            }
        }

        public virtual bool CheckRangeClick(MouseState mouseState, float left, float right, float top, float bottom)
        {
            if (mouseState.X >= left && mouseState.X <= right && mouseState.Y >= top && mouseState.Y <= bottom)
                return true;
            return false;
        }


        public virtual void CreateMonter(GameTime gameTime)
        {
            Random rdm = new Random();
            EnemySprite termMonter = new EnemySprite(monterSprite[0]);
            timeLastCreateMonter += gameTime.ElapsedGameTime.Milliseconds;
            if (timeLastCreateMonter > timeCreateMonter)
            {
                timeLastCreateMonter = 0;
                if (curNumberMonter < numberMonterSpriteAtTime)
                {
                    termMonter = CreateAMonter(gameTime, rdm.Next(nMonterSprite), rdm.Next(LINE));
                    listMonterSprite.Add(termMonter);
                    curNumberMonter++;
                    //remainMonterSprite--;
                }
            }

        }

        public virtual EnemySprite CreateAMonter(GameTime gameTime, int category, int line)
        {
            EnemySprite termMonter = new EnemySprite(monterSprite[0]);
            int x0 = Game.Window.ClientBounds.Width - 30;

            switch (category)
            {
                case 0:
                    {
                        termMonter = new EnemySprite(monterSprite[0]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 1:
                    {
                        termMonter = new EnemySprite(monterSprite[1]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 2:
                    {
                        termMonter = new EnemySprite(monterSprite[2]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 3:
                    {
                        termMonter = new EnemySprite(monterSprite[3]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 4:
                    {
                        termMonter = new EnemySprite(monterSprite[4]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 5:
                    {
                        termMonter = new EnemySprite(monterSprite[5]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 6:
                    {
                        termMonter = new EnemySprite(monterSprite[6]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
                case 7:
                    {
                        termMonter = new EnemySprite(monterSprite[7]);
                        switch (line)
                        {
                            case 0:
                                termMonter.Position = new Vector2(x0, 110);
                                break;
                            case 1:
                                termMonter.Position = new Vector2(x0, 220);
                                break;
                            case 2:
                                termMonter.Position = new Vector2(x0, 360);
                                break;
                            case 3:
                                termMonter.Position = new Vector2(x0, 500);
                                break;
                            case 4:
                                termMonter.Position = new Vector2(x0, 610);
                                break;
                            default:
                                break;

                        }
                        break;
                    }
            }

            return termMonter;
        }

        public void UpdatePlayer(GameTime gameTime)
        {
            //int n = listPlayerSpriteDraw.Count;
            //int m = listMonterSprite.Count;
            for (int i = 0; i < listPlayerSpriteDraw.Count; i++)
            {
                if (listPlayerSpriteDraw[i].IsLiving == false)
                {
                    listPlayerSpriteDraw.RemoveAt(i);
                }
            }

            foreach (PlayerSprite sprite in listPlayerSpriteDraw)//Update cac con sprite dc ve
            {
                sprite.Update(gameTime);
            }

        }

        public virtual void UpdateCollision(GameTime gameTime)
        {

            int n = listPlayerSpriteDraw.Count;
            int m = listMonterSprite.Count;

            //int a, b;
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    //Kiem tra collision giua player sprite voi bullet cua monter
                    foreach (EnermyBullet monterBullet in listMonterSprite[j].MonterBullets)
                    {
                        if (listPlayerSpriteDraw[i].collisionRect.Intersects(monterBullet.collisionRect))
                        {
                            if (monterBullet.Visible)
                            {
                                monterBulletSound.Play();
                                listPlayerSpriteDraw[i].Hp -= 20;
                                monterBullet.Visible = false;
                            }
                        }
                    }

                    //Kiem tra collision giua monter voi bullet cua player sprite
                    foreach (PlayerBullet playerBullet in listPlayerSpriteDraw[i].PlayerBullets)
                    {
                        if (playerBullet.collisionRect.Intersects(listMonterSprite[j].collisionRect))
                        {
                            if (playerBullet.Visible)
                            {
                                playerBulletSound.Play();
                                listMonterSprite[j].Hp -= 20;
                                playerBullet.Visible = false;
                            }
                        }
                    }

                    //Kiem tra collision giua player sprite voi monter
                    if (listPlayerSpriteDraw[i].collisionRect.Intersects(listMonterSprite[j].collisionRect))
                    {
                        monterCollisionSound.Play();
                        listPlayerSpriteDraw[i].IsLiving = false;
                        listMonterSprite[j].Hp -= 20;
                    }

                }
            }
        }
    }
}